home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / U-Z / VideoToolBox Folder / VideoToolboxSources / SetOnePixel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-23  |  9.7 KB  |  294 lines  |  [TEXT/KAHL]

  1. /*
  2. SetOnePixel.c
  3. NOTE: These routines are obsolete, retained solely for backward compatibility. 
  4. Use SetPixelsQuickly.c instead, since it's more than ten times faster in 
  5. most applications.
  6.  
  7. These are replacements for the official Apple SetCPixel, etc. Their virtue is
  8. that they're faster (but still slow) and don't translate your index via the
  9. color table. GetxxxPixel & SetxxxPixel all ignore the color spec arrays, giving
  10. you direct access to the unsigned number stored in the pixel (whether 1, 2, 4,
  11. 8, 16, or 32 bits)..
  12.  
  13. SetOnePixel(x,y,value);
  14. value=GetOnePixel(x,y);
  15. They use the current port. x and y are local coordinates.
  16.  
  17. SetPixmapPixel() and GetPixmapPixel() use the specified pixmap or bitmap.
  18.  
  19. SetDevicePixel() and GetDevicePixel() use the specified graphics device (i.e.
  20. monitor).
  21.  
  22. NOTE:
  23. If you are setting many contiguous pixels you will be wasting most of your time
  24. on the call overhead (once per pixel). That's why you should use
  25. SetPixelsQuickly.c instead.
  26.  
  27. These routines (and RectToAddress) do not "move memory", i.e. they don't give the
  28. Memory Manager any pretext for shuffling around the memory allocations, and
  29. change its master pointers. That's why it's OK to dereference the pixmap handle,
  30. i.e. use a local copy of the pixmap's master pointer.
  31.  
  32. All the routines in this file call either SetPixmapPixel or GetPixmapPixel. Both
  33. run fast by caching the information that they get about your Bit/Pixmap from
  34. RectToAddress. SetPixmapPixel and GetPixmapPixel each have their own cache.
  35.  
  36. HISTORY:
  37. 4/4/89    dgp wrote it as SetIPixel.c
  38. 9/8/90    dgp updated to work with 32 bit QuickDraw, if present.
  39. 10/15/90 bf renamed SetIPixelGW.c and modified for drawing to off screen pix maps.
  40. 4/26/92    dgp    Merged the two variants: SetIPixel.c and SetIPixelGW.c to produce the
  41.             new file SetOnePixel.c. 
  42.             Renamed SetIPixelGW to SetPixmapPixel.
  43.             Renamed GetIPixelGW to GetPixmapPixel.
  44.             Renamed SetIPixel to SetDevicePixel.
  45.             Renamed GetIPixel to GetDevicePixel.
  46.             Added SetOnePixel and GetOnePixel.
  47.             Generalized to handle any pixelSize, and accept bitmaps as well
  48.             as pixmaps.
  49. 12/23/92 dgp Doubled the speed of SetPixmapPixel and GetPixmapPixel (and thus sped up
  50.             all the routines that call them) by caching the answers from RectToAddress. 
  51.             The cache doubles the speed, but see CAUTION above.Introduced compile-time 
  52.             flag to optionally disable this new cache.
  53. 1/6/93 dgp    Fixed tiny but disastrous bug in GetPixmapPixel (wasn't saving old x and y).
  54. 1/22/93    dgp    Check more PixMap fields to make sure cache is not stale. Deleted the
  55.             warning about stale caches from the documentation.
  56. 2/7/93    dgp Wrote SetPixelsQuickly.c.
  57. */
  58. #include "VideoToolbox.h"
  59. #define USE_CACHE 1    // true or false
  60.  
  61. void SetOnePixel(int x,int y,unsigned long value)
  62. // Assumes (x,y) is in the local coordinate system of the current port.
  63. {
  64.     WindowPtr window;
  65.     PixMapPtr pm;
  66.     
  67.     GetPort(&window);
  68.     if(x<window->portRect.left || x>=window->portRect.right
  69.         || y<window->portRect.top || y>=window->portRect.bottom)return;
  70.     // Is it a CGrafPort or a GrafPort?
  71.     if(((CGrafPtr)window)->portVersion<0)        // It's a CGrafPort,
  72.         pm = *((CGrafPtr)window)->portPixMap;    // pass pixmap ptr.
  73.     else                                         // It's a GrafPort,
  74.         pm = (PixMapPtr) &window->portBits;        // pass bitmap ptr.
  75.     SetPixmapPixel(pm,x,y,value);
  76. }
  77.  
  78. unsigned long GetOnePixel(x,y)
  79. // Assumes (x,y) is in the local coordinate system of the current port.
  80. {
  81.     WindowPtr window;
  82.     PixMapPtr pm;
  83.     Rect *boundsPtr;
  84.     
  85.     GetPort(&window);
  86.     if(x<window->portRect.left || x>=window->portRect.right
  87.         || y<window->portRect.top || y>=window->portRect.bottom)return 0;
  88.     // Is it a CGrafPort or a GrafPort?
  89.     if(((CGrafPtr)window)->portVersion<0)        // It's a CGrafPort,
  90.         pm = *((CGrafPtr)window)->portPixMap;    // pass pixmap ptr.
  91.     else                                         // It's a GrafPort,
  92.         pm = (PixMapPtr) &window->portBits;        // pass bitmap ptr.
  93.     return GetPixmapPixel(pm,x,y);
  94. }
  95.  
  96. void SetPixmapPixel(register PixMapPtr pmPtr,int x,int y,unsigned long value)
  97. // Pokes a value into a pixel of any size. Accepts either pixmap or bitmap.
  98. // Assumes (x,y) is in the coordinate system of the bit/pixmap.
  99. // Speed is enhanced by reusing the cached information from last time if it's the
  100. // same Pix/Bitmap as last time, i.e. same address, baseAddr,rowBytes, and bounds.
  101. // You can force it to flush its cache by passing a NULL PixMap address.
  102. {
  103.     static PixMapPtr oldPmPtr=(PixMapPtr)-1;
  104.     static int oldX,oldY;
  105.     static short rowBytes,logPixelSize,bitsOffset;
  106.     static unsigned char *pixelPtr;
  107.     static BitMap oldMap;
  108.     int shift;
  109.     unsigned char mask;
  110.     char mode32=true32b;
  111.     Rect r;
  112.     
  113.     if(!USE_CACHE || pmPtr!=oldPmPtr
  114.         || pmPtr->baseAddr!=oldMap.baseAddr 
  115.         || pmPtr->rowBytes!=oldMap.rowBytes 
  116.         || *(long *)&pmPtr->bounds.top!=*(long *)&oldMap.bounds.top
  117.         || *(long *)&pmPtr->bounds.bottom!=*(long *)&oldMap.bounds.bottom){
  118.         // Cache is stale. Get fresh values.
  119.         short pixelSize;
  120.         SetRect(&r,x,y,x+1,y+1);
  121.         pixelPtr=RectToAddress(pmPtr,&r,&rowBytes,&pixelSize,&bitsOffset);
  122.         if(pixelPtr==NULL){
  123.             oldPmPtr=(PixMapPtr)-1;    // invalidate cache
  124.             return;
  125.         }
  126.         oldPmPtr=pmPtr;
  127.         oldMap=*(BitMap *)pmPtr;
  128.         logPixelSize=Log2L(pixelSize);
  129.     }else{
  130.         // Cache is fresh. Merely correct for changes in x and y.
  131.         if(pixelPtr==NULL)return;
  132.         if(logPixelSize<3){
  133.             register long bits;
  134.             bits=bitsOffset+(long)(x-oldX)<<logPixelSize;
  135.             pixelPtr+=bits>>3;
  136.             bitsOffset=bits&7;
  137.         }else pixelPtr+=(x-oldX)<<(logPixelSize-3);
  138.         if(y!=oldY)pixelPtr+=(long)(y-oldY)*rowBytes;
  139.     }
  140.     if(QD32Exists())SwapMMUMode(&mode32);
  141.     switch(logPixelSize){
  142.         register unsigned char val;
  143.     case 0:
  144.         shift=8-1-bitsOffset;    // from right, instead of from left
  145.         mask=1<<shift;
  146.         val=((unsigned char)value<<shift)&mask;
  147.         mask=~mask;
  148.         *pixelPtr= *pixelPtr & mask | (unsigned char)val;
  149.         break;
  150.     case 1:
  151.         shift=8-2-bitsOffset;    // from right, instead of from left
  152.         mask=3<<shift;
  153.         val=((unsigned char)value<<shift)&mask;
  154.         mask=~mask;
  155.         *pixelPtr= *pixelPtr & mask | (unsigned char)val;
  156.         break;
  157.     case 2:
  158.         shift=8-4-bitsOffset;    // from right, instead of from left
  159.         mask=15<<shift;
  160.         val=((unsigned char)value<<shift)&mask;
  161.         mask=~mask;
  162.         *pixelPtr= *pixelPtr & mask | (unsigned char)val;
  163.         break;
  164.     case 3:
  165.         *pixelPtr=value;
  166.         break;
  167.     case 4:
  168.         *(unsigned short *)pixelPtr=value;
  169.         break;
  170.     case 5:
  171.         *(unsigned long *)pixelPtr=value;
  172.         break;
  173.     }
  174.     if(QD32Exists())SwapMMUMode(&mode32);
  175.     oldX=x;
  176.     oldY=y;
  177. }
  178.  
  179. unsigned long GetPixmapPixel(register PixMapPtr pmPtr,int x,int y)
  180. // Returns the contents of a pixel of any size. Accepts either pixmap or bitmap.
  181. // Assumes (x,y) is in the coordinate system of the bit/pixmap.
  182. // Speed is enhanced by reusing the cached information from last time if it's the
  183. // same Pix/Bitmap as last time, i.e. same address, baseAddr,rowBytes, and bounds.
  184. // You can force it to flush its cache by passing a NULL PixMap address.
  185. {
  186.     static PixMapPtr oldPmPtr=(PixMapPtr)-1;
  187.     static int oldX,oldY;
  188.     static short rowBytes,logPixelSize,bitsOffset;
  189.     static unsigned char *pixelPtr;
  190.     static BitMap oldMap;
  191.     int shift;
  192.     unsigned char mask;
  193.     char mode32=true32b;
  194.     Rect r;
  195.     unsigned long value;
  196.     
  197.     if(!USE_CACHE || pmPtr!=oldPmPtr
  198.         || pmPtr->baseAddr!=oldMap.baseAddr 
  199.         || pmPtr->rowBytes!=oldMap.rowBytes 
  200.         || *(long *)&pmPtr->bounds.top!=*(long *)&oldMap.bounds.top
  201.         || *(long *)&pmPtr->bounds.bottom!=*(long *)&oldMap.bounds.bottom){
  202.         // Cache is stale. Get fresh values.
  203.         short pixelSize;
  204.         
  205.         SetRect(&r,x,y,x+1,y+1);
  206.         pixelPtr=RectToAddress(pmPtr,&r,&rowBytes,&pixelSize,&bitsOffset);
  207.         if(pixelPtr==NULL){
  208.             oldPmPtr=(PixMapPtr)-1;    // invalidate cache
  209.             return;
  210.         }
  211.         oldPmPtr=pmPtr;
  212.         oldMap=*(BitMap *)pmPtr;
  213.         logPixelSize=Log2L(pixelSize);
  214.     }else{
  215.         // Is already in cache. Merely correct for changes in x and y.
  216.         if(pixelPtr==NULL)return;
  217.         if(logPixelSize<3){
  218.             register long bits;
  219.             bits=bitsOffset+(long)(x-oldX)<<logPixelSize;
  220.             pixelPtr+=bits>>3;
  221.             bitsOffset=bits&7;
  222.         }else pixelPtr+=(x-oldX)<<(logPixelSize-3);
  223.         if(y!=oldY)pixelPtr+=(long)(y-oldY)*rowBytes;
  224.     }
  225.     if(QD32Exists())SwapMMUMode(&mode32);
  226.     switch(logPixelSize){
  227.     case 0:
  228.         shift=8-1-bitsOffset;    // from right, instead of from left
  229.         value=*pixelPtr>>shift & 1;
  230.         break;
  231.     case 1:
  232.         shift=8-2-bitsOffset;    // from right, instead of from left
  233.         value=*pixelPtr>>shift & 3;
  234.         break;
  235.     case 2:
  236.         shift=8-4-bitsOffset;    // from right, instead of from left
  237.         value=*pixelPtr>>shift & 15;
  238.         break;
  239.     case 3:
  240.         value=*pixelPtr;
  241.         break;
  242.     case 4:
  243.         value=*(unsigned short *)pixelPtr;
  244.         break;
  245.     case 5:
  246.         value=*(unsigned long *)pixelPtr;
  247.         break;
  248.     }
  249.     if(QD32Exists())SwapMMUMode(&mode32);
  250.     oldX=x;
  251.     oldY=y;
  252.     return value;
  253. }
  254.  
  255. void SetDevicePixel(GDHandle device,int x,int y,unsigned long value)
  256. // Assumes (x,y) is relative to the upper left hand corner of the screen.
  257. {
  258.     if(device==NULL)return;
  259.     x+=(*(*device)->gdPMap)->bounds.left;
  260.     y+=(*(*device)->gdPMap)->bounds.top;
  261.     SetPixmapPixel(*(*device)->gdPMap,x,y,value);
  262. }
  263.  
  264. unsigned long GetDevicePixel(GDHandle device,int x,int y)
  265. // Assumes (x,y) is relative to the upper left hand corner of the screen.
  266. {
  267.     if(device==NULL)return;
  268.     x+=(*(*device)->gdPMap)->bounds.left;
  269.     y+=(*(*device)->gdPMap)->bounds.top;
  270.     return GetPixmapPixel(*(*device)->gdPMap,x,y);
  271. }
  272.  
  273. /*
  274. // Slightly faster than RectToAddress, but much less general. 
  275. // Requires 8-bit pixelSize. It will give wrong answer when
  276. // the pixmap is derived from a window in a multi-screen environment.
  277. unsigned char *GetPixmapPixelAddress(PixMapPtr pmPtr,int x,int y)
  278. {
  279.     register unsigned char *pixelPtr;
  280.     
  281.     if(!(pmPtr->rowBytes & 0x8000) || pmPtr->pixelSize != 8) {
  282.         PrintfExit("GetPixmapPixelAddress(): sorry, I require 8 bits/pixel.\007\n");
  283.     }
  284.     if(x<pmPtr->bounds.left || x>=pmPtr->bounds.right
  285.         || y<pmPtr->bounds.top || y>=pmPtr->bounds.bottom)return NULL;
  286.     x-=pmPtr->bounds.left;
  287.     y-=pmPtr->bounds.top;
  288.     pixelPtr=(unsigned char *)pmPtr->baseAddr;
  289.     pixelPtr+=y*(long)(pmPtr->rowBytes & 0x1fff);
  290.     pixelPtr+=x;
  291.     return pixelPtr;
  292. }
  293. */
  294.